using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;

public partial class CameraRender
{
    ScriptableRenderContext context;
    Camera camera;

    const string bufferName = "Render Camera";
    CommandBuffer buffer = new CommandBuffer{name = bufferName};

    CullingResults cullingResults;

    
    static ShaderTagId[] customShaderTagIds =
    {
        new ShaderTagId("SRPDefaultUnlit"),
        new ShaderTagId("CustomLit"),
      //  new ShaderTagId("ShadowCaster"),
    };

    static int frameBufferId = Shader.PropertyToID("_CameraFrameBuffer");

    Lighting lighting = new Lighting();

    PostFXStack postFXStack = new PostFXStack();

    bool useHDR;


    void Setup()
    {
        context.SetupCameraProperties(camera);
        CameraClearFlags flags = camera.clearFlags;

        if (postFXStack.IsActive)
        {
            if (flags > CameraClearFlags.Color)
            {
                flags = CameraClearFlags.Color;
            }
            buffer.GetTemporaryRT(
                frameBufferId,
                camera.pixelWidth,
                camera.pixelHeight,
                32,
                FilterMode.Bilinear,
                this.useHDR ? RenderTextureFormat.DefaultHDR :  RenderTextureFormat.Default
                );
            buffer.SetRenderTarget(
                frameBufferId,
                RenderBufferLoadAction.DontCare,
                RenderBufferStoreAction.Store
                );
        }

        buffer.ClearRenderTarget(true, true, Color.clear);
        buffer.BeginSample(bufferName);
        ExecuteBuffer();

    }

    public void Render(ScriptableRenderContext context,Camera camera,
        bool useDynamicBatching, bool userGPUInstancing,
        ShadowSettings shadowSettings,
        PostFXSettings postFXSettings,
        bool allowHDR,
        int colorLUTResolution
        )
    {
        this.context = context;
        this.camera = camera;

        PrepareBuffer();
        PrepareForSceneWindow();

        if(!Cull(shadowSettings.maxDistance))
        {
            return;
        }
        useHDR = allowHDR && camera.allowHDR;

        buffer.BeginSample(bufferName);
        ExecuteBuffer();
        lighting.Setup(context, cullingResults, shadowSettings);
        postFXStack.Setup(context, camera, postFXSettings,this.useHDR, colorLUTResolution);
        buffer.EndSample(bufferName);

        Setup();      
        DrawVisibleGeometry(useDynamicBatching, userGPUInstancing);
        DrawUnsupportedShaders();

        DrawGizmosBeforeFX();
        if(postFXStack.IsActive)
        {
            postFXStack.Render(frameBufferId);
        }
        DrawGizmosAfterFX();

        Cleanup();
        Submit();
    }

    void Cleanup()
    {
        lighting.Cleanup();

        if(postFXStack.IsActive)
        {
            buffer.ReleaseTemporaryRT(frameBufferId);
        }
    }
   

    bool Cull(float maxShadowsDistance)
    {
        ScriptableCullingParameters p;
        if(camera.TryGetCullingParameters(out p))
        {
            p.shadowDistance =Mathf.Min(maxShadowsDistance,camera.farClipPlane);
            cullingResults = context.Cull(ref p);
            return true;
        }
        return false;
    }
   

    void DrawVisibleGeometry(bool useDynamicBatching,bool userGPUInstancing)
    {
        var sortingSettings = new SortingSettings(camera) {  criteria = SortingCriteria.CommonOpaque};
        var drawingSettings = new DrawingSettings(customShaderTagIds[0], sortingSettings) {
            enableDynamicBatching = useDynamicBatching,
            enableInstancing = userGPUInstancing,
            perObjectData = PerObjectData.Lightmaps             
            | PerObjectData.LightProbe
            | PerObjectData.LightProbeProxyVolume
            | PerObjectData.ShadowMask
            | PerObjectData.OcclusionProbe
            | PerObjectData.OcclusionProbeProxyVolume
            | PerObjectData.ReflectionProbes,
        };
       
        for (int i = 1; i < customShaderTagIds.Length; i++)
        {
            drawingSettings.SetShaderPassName(i, customShaderTagIds[i]);
        }
        /*
       */

        var filteringSettings = new FilteringSettings(RenderQueueRange.opaque);
        context.DrawRenderers(cullingResults,ref drawingSettings,ref filteringSettings);

        context.DrawSkybox(camera);

        sortingSettings.criteria = SortingCriteria.CommonTransparent;
        drawingSettings.sortingSettings = sortingSettings;
        filteringSettings.renderQueueRange = RenderQueueRange.transparent;
        context.DrawRenderers(cullingResults, ref drawingSettings, ref filteringSettings);
    }

    void ExecuteBuffer()
    {
        context.ExecuteCommandBuffer(buffer);
        buffer.Clear();
    }


    void Submit()
    {
        buffer.EndSample(bufferName);
        ExecuteBuffer();
        context.Submit();
    }

    partial void DrawUnsupportedShaders();
    partial void DrawGizmosBeforeFX();
    partial void DrawGizmosAfterFX();
    partial void PrepareForSceneWindow();

    partial void PrepareBuffer();

}
